home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume17 / zoo2 / part03 < prev    next >
Encoding:
Internet Message Format  |  1989-02-01  |  49.2 KB

  1. Subject:  v17i066:  Zoo archive program, Part03/10
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4.  
  5. Submitted-by: Rahul Dhesi <bsu-cs!dhesi@iuvax.cs.indiana.edu>
  6. Posting-number: Volume 17, Issue 66
  7. Archive-name: zoo2/part03
  8.  
  9. #! /bin/sh
  10. # This is a shell archive.  Remove anything before this line, then unpack
  11. # it by saving it into a file and typing "sh file".  To overwrite existing
  12. # files, type "sh file -c".  You can also feed this as standard input via
  13. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  14. # will see the following message at the end:
  15. #        "End of archive 3 (of 10)."
  16. # Wrapped by rsalz@papaya.bbn.com on Thu Feb  2 18:03:58 1989
  17. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  18. if test -f 'Install' -a "${1}" != "-c" ; then 
  19.   echo shar: Will not clobber existing file \"'Install'\"
  20. else
  21. echo shar: Extracting \"'Install'\" \(7622 characters\)
  22. sed "s/^X//" >'Install' <<'END_OF_FILE'
  23. X
  24. X
  25. X                              INSTALLATION
  26. X
  27. X
  28. XThis document explains how to compile and install the zoo archiver.
  29. X
  30. XGenerally, you will not build zoo by directly invoking the supplied
  31. Xmakefile.  Instead, you will execute one of the supplied scripts, or
  32. Xcreate a suitable script.  Each supplied script has a name beginning
  33. Xwith the characters "mk" and is executed with the command
  34. X"sh scriptname" or "csh scriptname".  All the scripts listed below
  35. Xworked correctly with version 1.50 of zoo.  All of them except mkx68 and
  36. Xmkx86 are also known to work correctly for versions 1.71, 2.00, and
  37. X2.01.
  38. X
  39. Xmksysv    This is for any system running System V Release 2 or something
  40. X          reasonably compatible.  It is known to work on the *T&T **IX
  41. X          PC (also known as the 3B1 or the *T&T 7300) running software
  42. X          revision 3.0.  It should also work on more recent versions of
  43. X          Xenix.  On older machine architectures this script may need to
  44. X          be revised to add a `-Ml' switch or equivalent to cause the
  45. X          large memory model to be used.  For Microport System V/AT and
  46. X          Xenix see also descriptions for mkuport, mkx86, and mkx68.
  47. X
  48. Xmkbsd     This is for 4.3BSD.  It is known to work on a VAX-11/785 run-
  49. X          ning 4.3BSD straight from Berkeley.
  50. X
  51. Xmkuport   For Microport System V/AT.  This script includes the -Ml
  52. X          switch so that the large memory model is used.
  53. X
  54. Xmkx68     This script is for Xenix/68000.  It is known to work with zoo
  55. X          version 1.50 on a Radio Shack Model 16 running Xenix version
  56. X          3.01.01.  It takes care of problems in the C compiler and in
  57. X          the include files related to incorrect handling of the `void'
  58. X          data type.  However, since this version of Xenix does not have
  59. X          the memset() library function, the line "#define MEMSET" may
  60. X          first need to be commented out from the group of symbol defin-
  61. X          itions for SYS_V in the file ``options.h''.  You may also need
  62. X          to add the switch "-F 6000" (or some other reasonable value
  63. X          instead of 6000) to the loader to make it allocate a bigger
  64. X          stack.
  65. X
  66. Xmkx86     This script is for Xenix for 80286 systems.  It is known to
  67. X          work (for zoo version 1.50) on an Intel 310/286 running Xenix
  68. X          3.4 and an AT running SCO Xenix 2.2.  It causes the large
  69. X          memory model to be used and sufficient stack space to be allo-
  70. X          cated at load time.
  71. X
  72. Xdescrip.mms This is a makefile suitable for use on VAX/VMS systems with
  73. X          DEC's version of make, called MMS.  It is believed to work on
  74. X          versions 4.5 through 4.7 of VAX/VMS.  The target zoo.exe
  75. X          directs the linker to use the file options.opt so that the
  76. X          shareable library is used.  The target zoobig.exe is identical
  77. X          except that the shareable library is not used, making the exe-
  78. X          cutable program about twice as big.
  79. X
  80. X          Special techniques are needed to work around numerous pecu-
  81. X          liarities in VAX/VMS.  These are described separately in the
  82. X          file ``vmsbugs.doc''.  In particular, the VAX/VMS version of
  83. X          zoo must be used in conjunction with the "bilf.exe" utility,
  84. X          which performs needed file conversions.  The source program
  85. X          bilf.c is included in the current source distribution for zoo.
  86. X
  87. XThe file ``options.h'' defines preprocessor symbols for the various sys-
  88. Xtems.  In most cases, given a reasonably powerful C compiler and
  89. Xlibrary, you will be able to find a combination of options that will
  90. Xwork.  Documentation for these options is in the file ``options.doc''.
  91. X
  92. XOther machine-dependent code and definitions are in machine.h,
  93. Xmachine.c, and portable.h.  Also, the amount of memory used for various
  94. Xarrays can be customized by defining symbols that are described and used
  95. Xin zoomem.h.
  96. X
  97. XThe low-level input/output routines are in portable.c.  In most cases
  98. Xthese will not need to be modified.
  99. X
  100. XThe zoo source code largely conforms to the requirements of Kernighan
  101. Xand Ritchie's book.  Some exceptions are as follows.
  102. X
  103. X   - Variables are believed to be unique in their initial 8 characters.
  104. X     Systems that distinguish fewer than 8 initial characters are
  105. X     currently not supported.
  106. X
  107. X   - Zoo code assumes that members of structures do not have global
  108. X     scope.
  109. X
  110. X   - Long preprocessor symbols are occasionally used.
  111. X
  112. X   - The special value -1 is cast to a pointer of type (FILE *) to pro-
  113. X     vide a distinguished file pointer that is used to signify output to
  114. X     a null file.  This should work on most systems that support the
  115. X     system call sbrk.  Any suitable value may be supplied in place of
  116. X     -1 in zooio.h.
  117. X
  118. XTROUBLESHOOTING.
  119. X
  120. XAs currently configured for **IX variants, zoo uses the access() system
  121. Xcall to check for file existence (see the definition for the symbol
  122. XEXISTS in options.h).  There is some question about the appropriatenes
  123. Xof this, because access() can give the wrong answer when used from a
  124. Xset-user-id program.  If EXISTS is left undefined, zoo uses its own
  125. Xfunction to test for file existence by trying to open the file for read
  126. Xand also for write.
  127. X
  128. XTwo common reasons for crashes when zoo is executed are the following.
  129. X
  130. X   - On machines with older (Intel-style) architectures zoo requires the
  131. X     large memory model.  Compiling with the small memory model will
  132. X     cause problems.  Also, systems that are limited to 64 kilobytes of
  133. X     data and 64 kilobytes of code are not currently supported (but they
  134. X     will be in the future).
  135. X
  136. X   - A generous amount of stack space is needed.  Depending on the sys-
  137. X     tem, this will vary from about 15 kilobytes to about 33 kilobytes.
  138. X     On systems that cannot expand the stack dynamically you will need
  139. X     to specify the size of the stack area at load time.
  140. X
  141. XSPECIAL VERSIONS.  A version (currently 2.01) is available for MS-DOS
  142. Xthat provides better performance due to assembly language routines and
  143. Xalso includes some system-dependent features.  Another version
  144. X(currently 2.00) has been ported by J. Brian Waters for the Amiga.  It
  145. Xincludes several AmigaDOS-dependent features such as preservation of
  146. Xfile times and wildcard expansion.
  147. X
  148. XEXTRACT-ONLY VERSIONS.  For a new system, your first concern should be
  149. Xthe ability to extract and list zoo archives.  For this purpose try com-
  150. Xpiling booz (which stands for Barebones Ooz) (currently version 1.01),
  151. Xwhich can be compiled with three different options requiring different
  152. Xdegrees of compiler sophistication and offering different levels of
  153. Xfeatures.  Unlike zoo, booz will work on systems with less than 64 kilo-
  154. Xbytes of total available memory.  However, unlike zoo, booz uses low-
  155. Xlevel unbuffered file descriptors in **IX style.  This program is not a
  156. Xpart of the standard zoo distribution, because nobody has ever shown any
  157. Xinterest in it.
  158. X
  159. XMachine-dependencies.
  160. X
  161. X   - Currently the only systems supported are those that can read and
  162. X     write in 8-bit units.  The file ``machine.h'' contains a typedef of
  163. X     BYTE, and it must be defined to be an 8-bit quantity.
  164. X
  165. X   - It is not known whether zoo code as it stands will work on a 1's-
  166. X     complement machine.
  167. X
  168. X   - The code assumes that type `int' is at least 16 bits long and type
  169. X     `long' is at least 32 bits long.  There may be some implicit
  170. X     assumptions that type `char' is exactly 8 bits;  I am not sure if
  171. X     this is so.  However, type `BYTE' must be exactly 8 bits long.
  172. X
  173. X   - In accordance with K&R (p 126), zoo code assumes that sizeof(char)
  174. X     equals exactly 1.
  175. X
  176. X                                     -- Rahul Dhesi 1988/08/25
  177. END_OF_FILE
  178. if test 7622 -ne `wc -c <'Install'`; then
  179.     echo shar: \"'Install'\" unpacked with wrong size!
  180. fi
  181. # end of 'Install'
  182. fi
  183. if test -f 'bilf.c' -a "${1}" != "-c" ; then 
  184.   echo shar: Will not clobber existing file \"'bilf.c'\"
  185. else
  186. echo shar: Extracting \"'bilf.c'\" \(6109 characters\)
  187. sed "s/^X//" >'bilf.c' <<'END_OF_FILE'
  188. X/*
  189. XThis program performs conversion of files between stream-LF format
  190. X(as used by zoo) and fixed-length record binary format (used for Kermit
  191. Xtransfers of zoo archives).
  192. X
  193. XThis program is:
  194. X   (C) Copyright 1987 Rahul Dhesi.
  195. X   All Rights Reserved.
  196. X
  197. XPermission is hereby granted to copy and modify this for any purpose,
  198. Xwhether commercial or noncommercial, provided only that the above
  199. Xcopyright notice and this paragraph be preserved and included
  200. Xin all copies.
  201. X
  202. X                                 -- Rahul Dhesi 1987/07/25
  203. X*/
  204. X
  205. X#include <stdio.h>
  206. X#include <ssdef.h>
  207. X#define STAT_NORM SS$_NORMAL
  208. X#define STAT_ABORT SS$_ABORT
  209. X
  210. Xchar *strrchr();
  211. Xchar *strdup ();
  212. X
  213. Xmain (argc, argv)
  214. Xint argc;
  215. Xchar *argv[];
  216. X{
  217. X   char *inname;
  218. X   char *outname;
  219. X   char *option;
  220. X   int status;
  221. X
  222. X   if (argc < 3 || argc > 4) {
  223. X      printf ("BILF version 1.00 for VAX/VMS by Rahul Dhesi (1987/07/25)\n\n");
  224. X      printf ("(C) Copyright 1987 Rahul Dhesi,  All Rights Reserved\n");
  225. X      printf ("Permission to use and distribute is granted provided this copyright\n"); 
  226. X      printf ("notice is preserved and included in all copies.\n\n");
  227. X      printf ("Usage:  BILF {lb} infile [ outfile ]\n\n");
  228. X      printf ("Choose one character from within braces.  If outfile is not supplied\n");
  229. X      printf ("it has the same name as infile but a higher version number.\n");
  230. X      printf ("Options are:\n\n");
  231. X      printf ("l:  Write output file in stream-LF format.  This is the format that\n");
  232. X      printf ("    zoo expects all zoo archives to be in.  If a zoo archive was\n");
  233. X      printf ("    uploaded to a VAX/VMS system, it will need to be converted to\n");
  234. X      printf ("    stream-LF format before manipulating with zoo.\n\n");
  235. X      printf ("b:  Write output file in fixed-length 512-byte binary record format.  Before\n");
  236. X      printf ("    a zoo archive can be downloaded from a VAX/VMS system to a\n");
  237. X      printf ("    microcomputer using VAX/VMS Kermit, it must be converted to\n");
  238. X      printf ("    this binary format.  Failure to do so will result in a corrupted\n");
  239. X      printf ("    download.\n");
  240. X      exit (STAT_NORM);
  241. X   }
  242. X
  243. X   inname = argv[2];
  244. X   option = argv[1];
  245. X
  246. X   if (argc == 3) {                    /* use same filename for output */
  247. X      char *p;
  248. X      outname = strdup (inname);
  249. X      p = strrchr (outname, ';');      /* strip trailing version field */
  250. X      if (p != NULL)
  251. X         *p = '\0';
  252. X   } else
  253. X      outname = argv[3];
  254. X
  255. X   if (*option == 'l')
  256. X      status = cvtstream (outname, inname);
  257. X   else if (*option == 'b')
  258. X      status = cvtbin (outname, inname);
  259. X   else
  260. X      prterror ('f', "Option %s is invalid\n", option);
  261. X   if (status == -1)
  262. X      prterror ('w', "An error occurred -- output file may be corrupted\n");
  263. X   exit (STAT_NORM);
  264. X}
  265. X
  266. X#define  MYBUFSIZ    8192
  267. X
  268. X/* writes input file to output file in stream format */
  269. Xint cvtstream (outname, inname)
  270. Xchar *outname, *inname;
  271. X{
  272. X   FILE *infile, *outfile;
  273. X   char buffer[MYBUFSIZ];
  274. X   int count;
  275. X
  276. X   infile = fopen (inname, "r");
  277. X   if (infile == NULL)
  278. X      prterror ('f', "Could not open input file %s\n", inname);
  279. X   outfile = fopen (outname, "w");
  280. X   if (outfile == NULL)
  281. X      prterror ('f', "Could not open output file %s\n", outname);
  282. X
  283. X   while ((count = fread (buffer, 1, sizeof (buffer), infile)) > 0)
  284. X      count = fwrite (buffer, 1, count, outfile);
  285. X
  286. X   close (infile); close (outfile);
  287. X   if (count == -1)
  288. X      return (-1);
  289. X   else
  290. X      return (0);
  291. X}
  292. X
  293. X/*
  294. XVMS C doesn't have strdup().
  295. X*/
  296. Xchar *strdup (str)
  297. Xchar *str;
  298. X{
  299. X   char *malloc();
  300. X   char *newstr = malloc (strlen (str) + 1);
  301. X   if (newstr != NULL) {
  302. X      strcpy (newstr, str);
  303. X      return (newstr);
  304. X   } else
  305. X      return ((char *) NULL);
  306. X}
  307. X
  308. X/* BLKSIZ must correspond to block size specified below in creat() */
  309. X#define BLKSIZ 512
  310. X
  311. X/*
  312. XWrites input file to output in fixed-length BLKSIZ-byte record format.
  313. X*/
  314. X
  315. X#if 1
  316. X#include <file.h>
  317. X#else
  318. X#include <fcntl.h>
  319. X#endif
  320. X
  321. Xint convert ();
  322. X
  323. Xint cvtbin (outname, inname)
  324. Xchar *outname, *inname;
  325. X{
  326. X   int status, inhan, outhan;
  327. X   inhan = open (inname, O_RDONLY);
  328. X   if (inhan == -1)
  329. X      prterror ('f', "Could not open input file %s\n", inname);
  330. X   outhan = creat (outname, 0, "rfm=fix", "mrs=512");
  331. X   if (outhan == -1)
  332. X      prterror ('f', "Could not open output file %s\n", outname);
  333. X   status = convert (outhan, inhan);
  334. X   close (inhan);
  335. X   close (outhan);
  336. X   return (status);
  337. X}
  338. X
  339. X/*
  340. XFunction convert() reads from inhan and writes to outhan, always
  341. Xwriting in BLKSIZ-byte blocks, padding with nulls if necessary
  342. X*/
  343. X
  344. Xint convert (outhan, inhan)
  345. Xint inhan, outhan;
  346. X{
  347. X   char junk[BLKSIZ];
  348. X   int count;
  349. X   int done = 0;
  350. X   do {
  351. X      count = vmsread (inhan, junk, BLKSIZ);
  352. X      if (count <= 0)
  353. X         break;
  354. X      if (count < BLKSIZ) {
  355. X         int i;
  356. X         for (i = count; i < BLKSIZ; i++)
  357. X            junk[i] = 0;
  358. X         done++;
  359. X      }
  360. X      count = write (outhan, junk, BLKSIZ);
  361. X      if (count == -1)
  362. X         break;
  363. X   } while (!done);
  364. X   if (count == -1)
  365. X      return (-1);
  366. X   else
  367. X      return (0);
  368. X}
  369. X
  370. X/**** Function vmsread() does a standard read() but gets around bugs
  371. Xin the read() function of VAX/VMS C which make it unable to always
  372. Xread the entire amount requested in a single read() call.
  373. X*/
  374. Xint vmsread (han, buf, amount)
  375. Xint han;
  376. Xchar *buf;
  377. Xint amount;
  378. X{
  379. X   int count;
  380. X   int thiscount;
  381. X   count = 0;
  382. X   while (count != -1 && count < amount) {
  383. X      thiscount = read (han, &buf[count], amount - count);
  384. X      if (thiscount == 0)
  385. X         thiscount = read (han, &buf[count], amount - count);
  386. X      if (thiscount == 0)
  387. X          break;
  388. X      if (thiscount == -1)
  389. X         count = -1;
  390. X      else
  391. X         count += thiscount;
  392. X   }
  393. X   return (count);
  394. X}
  395. X
  396. Xprterror (level, msg1, msg2)
  397. Xchar level;
  398. Xchar *msg1, *msg2;
  399. X{
  400. X   if (level == 'e' || level == 'w' || level == 'f')
  401. X      printf ("BILF: ");
  402. X
  403. X   switch (level) {
  404. X      case 'e': printf ("ERROR: ");    break;
  405. X      case 'w': printf ("WARNING: ");  break;
  406. X      case 'f': printf ("FATAL: ");    break;
  407. X      default:  prterror ('f', "Internal error in prterror()\n");
  408. X   }
  409. X
  410. X   printf (msg1, msg2);
  411. X   if (level == 'f')
  412. X      exit (STAT_ABORT);
  413. X}
  414. END_OF_FILE
  415. if test 6109 -ne `wc -c <'bilf.c'`; then
  416.     echo shar: \"'bilf.c'\" unpacked with wrong size!
  417. fi
  418. # end of 'bilf.c'
  419. fi
  420. if test -f 'fiz.c' -a "${1}" != "-c" ; then 
  421.   echo shar: Will not clobber existing file \"'fiz.c'\"
  422. else
  423. echo shar: Extracting \"'fiz.c'\" \(6864 characters\)
  424. sed "s/^X//" >'fiz.c' <<'END_OF_FILE'
  425. X#ifndef LINT
  426. Xstatic char sccsid[]="@(#) fiz.c 2.6 88/01/31 23:23:50";
  427. X#endif /* LINT */
  428. X
  429. X/*
  430. XThe contents of this file are hereby released to the public domain.
  431. X
  432. X                                   -- Rahul Dhesi 1987/02/06
  433. X*/
  434. X
  435. X/*
  436. XSearches for all directory entries in an archive and prints their
  437. Xoffsets.  Zoo 1.41 and later may then be asked to extract a specific
  438. Xfile by supplying the offset of the file.
  439. X*/
  440. X
  441. X#include "options.h"
  442. X#include "zooio.h"
  443. X#include "various.h"
  444. X#include "zoofns.h"
  445. X#include "portable.h"         /* I/O definitions */
  446. X#include "zoo.h"
  447. X
  448. X#ifdef LINT_ARGS
  449. Xvoid prtctrl (char *);
  450. Xvoid prtch (unsigned int);
  451. X#else
  452. Xvoid prtctrl ();
  453. Xvoid prtch ();
  454. X#endif
  455. X
  456. Xmain(argc,argv)
  457. Xregister int argc;
  458. Xregister char **argv;
  459. X{
  460. X   char *zooname;          /* name of archive to be read */
  461. X   ZOOFILE zoo_file;       /* the archive being examined opened for read */
  462. X   int state;              /* to keep track of how much of tag seen */
  463. X   int inch;               /* char just read from archive */
  464. X
  465. X   static char usage1[] = "Fiz 2.0 (1987/02/01) public domain Zoo archive repair utility by Rahul Dhesi\n";
  466. X   static char usage2[] = "Usage:  fiz archive[.zoo]  (\"fiz -h\" for help)\n";
  467. X
  468. X#ifdef SETBUF
  469. X/* set stdout to unbuffered */
  470. Xsetbuf (stdout, (char *) NULL);
  471. X#endif
  472. X
  473. X   if (argc < 2) {
  474. X      printf("%s%s", usage1, usage2);
  475. X      exit (1);
  476. X   }
  477. X
  478. X   if (strcmp(argv[1],"-h") == 0)
  479. X      goto givehelp;
  480. X
  481. X   zooname = argv[1];
  482. X
  483. X   /* Add default extension if none supplied */
  484. X   {
  485. X      char *p, *q;
  486. X      p = zooname + strlen(zooname);         /* point to last char */
  487. X      while (p != zooname && *p != EXT_CH)
  488. X         --p;
  489. X      /* either found EXT_CH or reached beginning of zooname */
  490. X      if (*p != EXT_CH) {
  491. X         q = malloc(strlen(zooname) + strlen(EXT_DFLT) + 2);
  492. X         if (q == NULL) {
  493. X            printf("Fiz:  Ran out of memory.\n");
  494. X            exit(1);
  495. X         }
  496. X         strcpy(q, zooname);
  497. X         strcat(q, EXT_DFLT);
  498. X         zooname = q;
  499. X      }
  500. X   }
  501. X
  502. X   zoo_file = zooopen (zooname, Z_READ);
  503. X   if (zoo_file == NOFILE) {
  504. X      printf("Fiz:  FATAL:  Could not open %s.\n", zooname);
  505. X      exit(1);
  506. X   }
  507. X
  508. X#ifdef DOUBLE_SECRET
  509. X    { void oh_well(void); oh_well(); }
  510. X#endif
  511. X
  512. X#define  NOSTATE  1
  513. X#define  HDR_1   0xdc
  514. X#define  HDR_2   0xa7
  515. X#define  HDR_3   0xc4
  516. X#define  HDR_4   0xfd
  517. X
  518. X#define    DAT_1   '@'
  519. X#define    DAT_2   ')'
  520. X#define    DAT_3   '#'
  521. X#define    DAT_4   '('
  522. X
  523. X/* finite state machine implemented here by hand */
  524. X
  525. X   state = NOSTATE;
  526. X   while ((inch = zgetc(zoo_file)) != EOF) {
  527. X      inch = inch & 0xff;
  528. X      if (state == NOSTATE) {
  529. X            if (inch == HDR_1)
  530. X                state = HDR_1;
  531. X            else if (inch == DAT_1)
  532. X                state = DAT_1;
  533. X        } else if (state == HDR_1 && inch == HDR_2)
  534. X         state = HDR_2;
  535. X      else if (state == HDR_2 && inch == HDR_3)
  536. X         state = HDR_3;
  537. X      else if (state == HDR_3 && inch == HDR_4)
  538. X         state = HDR_4;
  539. X        else if (state == DAT_1 && inch == DAT_2)
  540. X            state = DAT_2;
  541. X        else if (state == DAT_2 && inch == DAT_3)
  542. X            state = DAT_3;
  543. X        else if (state == DAT_3 && inch == DAT_4)
  544. X            state = DAT_4;
  545. X      else
  546. X         state = NOSTATE;
  547. X
  548. X      if (state == HDR_4) {                                   /* found archive tag */
  549. X         long save_pos;
  550. X         struct direntry direntry;
  551. X         save_pos = zootell(zoo_file);
  552. X         zooseek(zoo_file, save_pos-4L, 0);                /* back to tag pos */
  553. X         frd_dir(&direntry, zoo_file);                        /* read dir entry */
  554. X         printf("****************\n");
  555. X
  556. X         printf ("%8lu: DIR ", save_pos-4L);
  557. X
  558. X         if (direntry.dirlen > 0) {
  559. X            printf ("[");
  560. X            prtctrl (direntry.dirname);
  561. X            printf ("]");
  562. X         }
  563. X
  564. X         printf(" [");
  565. X         prtctrl (direntry.fname);
  566. X         printf ("]");
  567. X
  568. X         if (direntry.namlen > 0) {
  569. X            printf (" [");
  570. X            prtctrl (direntry.lfname);
  571. X            printf ("]");
  572. X         }
  573. X            printf (" ==> %4lu", direntry.offset);
  574. X         if (direntry.dir_crc != 0)
  575. X            printf (" [*bad CRC*]");
  576. X         printf ("\n");
  577. X         fseek (zoo_file, save_pos, 0);         /* try again from there */
  578. X      } else if (state == DAT_4) {                /* file data */
  579. X         printf ("%8lu: DATA\n", zootell(zoo_file) + 1);
  580. X        }
  581. X   }
  582. Xexit (0);      /* don't fall through */
  583. X
  584. Xgivehelp:
  585. X
  586. X/*
  587. Xvi macros:
  588. Xto add printf:
  589. X:s/^.*$/printf("&\\n");/
  590. XTo remove printf:
  591. X:s/^printf("\(.*\)\\n");/\1/
  592. X*/
  593. Xprintf("Fiz is used to help you recover data from a damaged archive.  Fiz searches\n");
  594. Xprintf("the specified archive for directory entries and stored files, and prints the\n");
  595. Xprintf("position of each one found.  Each directory entry contains a number that\n");
  596. Xprintf("represents the location in the archive where the file is stored;  fiz also\n");
  597. Xprintf("prints this position.  All numbers printed are decimal numbers.\n\n");
  598. X
  599. Xprintf("Use Zoo version 2.00 or higher to list or extract files in the damaged\n");
  600. Xprintf("archive starting at a position identified by fiz.  For example, you can\n");
  601. Xprintf("start extracting files from archive \"badarc.zoo\" at position 1098 with the\n");
  602. Xprintf("command:\n\n");
  603. X
  604. Xprintf("     zoo x@1098 badarc\n\n");
  605. X
  606. Xprintf("Zoo will ignore the first 1098 bytes of the damaged archive and you should be\n");
  607. Xprintf("able to recover the undamaged files from the rest of the archive.  You can\n");
  608. Xprintf("also manually specify where to look for the file data with a command like\n\n");
  609. X
  610. Xprintf("     zoo x@1098,1153\n\n");
  611. X
  612. Xprintf("which tells zoo to use the directory entry at position 1098, but to get the\n");
  613. Xprintf("actual file data from position 1153 (and not from where the directory entry\n");
  614. Xprintf("says the data ought to be).  See the manuals for fiz and zoo for more details.\n");
  615. X
  616. Xexit (0);
  617. X}
  618. X
  619. X/*
  620. Xprtctrl() prints a string with all unprintable characters converted
  621. Xto printable form.  To avoid the program running astray trying to
  622. Xprint damaged data, no more than MAXPRT characters are printed.
  623. XCharacters with the 8th bit set are printed preceded with ~.  Control
  624. Xcharacters are printed preceded with ^.  Both ~ and ^ may preced
  625. Xthe character if a control character has the 8th bit set.
  626. X*/
  627. X#define  MAXPRT      50
  628. X
  629. Xvoid prtctrl (str)
  630. Xchar *str;
  631. X{
  632. X   unsigned int ch;
  633. X   int count;
  634. X   count = 0;
  635. X
  636. X   while (count < MAXPRT && *str != '\0') {
  637. X      ch = (unsigned) *str;
  638. X      prtch(ch);
  639. X      str++;
  640. X      count++;
  641. X   }
  642. X}
  643. X
  644. X/*
  645. XDoes the actual character printing for prtctrl()
  646. X*/
  647. Xvoid prtch(ch)
  648. Xunsigned int ch;
  649. X{
  650. X   /* assumes ASCII character set */
  651. X   if (ch < ' ') {                        /* ^@ through ^_ */
  652. X      printf("^%c", ch + 0x40);
  653. X   } else if (ch == 0x7f) {               /* DEL */
  654. X      printf("^?");
  655. X   } else if (ch > 0x7f) {                /* 8th bit set */
  656. X      printf("~");                        /* .. so precede with ~ */
  657. X      prtch(ch & 0x7f);                   /* slick recursive call */
  658. X   } else
  659. X      printf("%c", ch);                   /* plain char */
  660. X}
  661. END_OF_FILE
  662. if test 6864 -ne `wc -c <'fiz.c'`; then
  663.     echo shar: \"'fiz.c'\" unpacked with wrong size!
  664. fi
  665. # end of 'fiz.c'
  666. fi
  667. if test -f 'makelist.c' -a "${1}" != "-c" ; then 
  668.   echo shar: Will not clobber existing file \"'makelist.c'\"
  669. else
  670. echo shar: Extracting \"'makelist.c'\" \(6233 characters\)
  671. sed "s/^X//" >'makelist.c' <<'END_OF_FILE'
  672. X#ifndef LINT
  673. X/* @(#) makelist.c 2.3 88/01/24 12:46:44 */
  674. Xstatic char sccsid[]="@(#) makelist.c 2.3 88/01/24 12:46:44";
  675. X#endif /* LINT */
  676. X
  677. X/*
  678. XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
  679. X(C) Copyright 1988 Rahul Dhesi -- All rights reserved
  680. X*/
  681. X
  682. X#include "options.h"
  683. X#include "portable.h"
  684. X#include "errors.i"
  685. X#include "zoo.h"
  686. X#include "zooio.h"
  687. X#include "various.h"
  688. X
  689. X#include "zoofns.h"
  690. X#include "assert.h"
  691. X#include "debug.h"
  692. X
  693. X#ifdef LINT_ARGS
  694. Xchar *nameptr (char *);
  695. Xvoid modpath (char *);
  696. X#else
  697. Xchar *nameptr();
  698. Xvoid modpath ();
  699. X#endif
  700. X
  701. X/*******************/
  702. X/*
  703. Xmakelist() gets all pathnames corresponding to a set of filespecs and
  704. Xadds them to a list.  Not more than "flistsize" pathnames are added.
  705. XInto `longest' it returns the length of the longest name added, or
  706. Xzero if none added.
  707. X
  708. XFiles ignore1, ignore2, and ignore3 are not added to the list.
  709. XA file that is a device/directory is also not added to the list.
  710. X
  711. XHowever, if ignore1 is NULL, both these tests are skipped and all files
  712. Xwill be added to the list.
  713. X*/
  714. X
  715. Xvoid makelist (argc, argv, flist, flistsize, ignore1, ignore2, ignore3, longest)
  716. Xint argc;               /* number of filespec supplied */
  717. Xchar *argv[];           /* array of pointers to supplied filespecs */
  718. Xregister char *flist[]; /* array of pointers to filenames we will add */
  719. Xint flistsize;          /* home many names we can use */
  720. Xchar *ignore1, *ignore2, *ignore3; /* files to exclude from list */
  721. Xint *longest;        /* length of longest name in list */
  722. X{
  723. X   char *this_path;        /* current pathname */
  724. X   int fptr;               /* pointer to within flist */
  725. X   register int i, j;      /* loop counters */
  726. X
  727. X#ifdef WILDCARD
  728. X   char *pat_name;         /* filename part of pattern */
  729. X#endif
  730. X
  731. X   int gap;                /* for Shell sort */
  732. X   
  733. X   flistsize--;            /* allow for one terminating NULL entry */
  734. X   fptr = *longest = 0;
  735. X
  736. X   assert(argc > 0);
  737. X
  738. X#define WCLEN    4    /* length needed for wildcard, and a little extra */
  739. X
  740. X   while (argc > 0) {
  741. X#ifdef WILDCARD
  742. X        int argok = 0;                                            /* arg not matched yet */
  743. X#endif
  744. X      char *this_arg;
  745. X        this_arg = emalloc (strlen (*argv) + WCLEN);
  746. X        strcpy (this_arg, *argv);
  747. X
  748. X      /* Initialize fileset 0.  Select all files -- we will later
  749. X             filter out the ones wanted */
  750. X#ifdef FOLD
  751. X      strlwr (this_arg);
  752. X#endif
  753. X
  754. X#ifdef WILDCARD
  755. X      pat_name = strdup (nameptr (this_arg));        /* pattern without path */
  756. X#ifdef VER_CH /* trailing version field */
  757. X{
  758. X   static char version_field[] = " *";
  759. X   char *p;
  760. X   p = strrchr (pat_name, VER_CH);
  761. X   if (p == NULL) {
  762. X      *version_field = VER_CH;
  763. X      pat_name = newcat (pat_name, version_field); /* adds trailing ";*" */
  764. X   }
  765. X}
  766. X#endif
  767. X        /*
  768. X        replace filename by wildcard;  however, if argument ends in slash, 
  769. X        then simply append wildcard so we get all files in that directory
  770. X        */
  771. X#ifdef FORCESLASH
  772. X            fixslash (this_arg);                /* convert backslashes to slashes */
  773. X#endif
  774. X
  775. X        if (*lastptr(this_arg) == *PATH_CH) {
  776. X            strcat (this_arg, WILDCARD);
  777. X            pat_name = "*";                    /* and select all files */
  778. X        } else
  779. X#ifdef SPEC_WILD
  780. X            spec_wild (this_arg);
  781. X#else
  782. X          strcpy (nameptr (this_arg), WILDCARD);
  783. X#endif /* SPEC_WILD */
  784. X#endif /* WILDCARD */
  785. X
  786. X      nextfile (0, this_arg, 0);
  787. X      while (fptr < flistsize && 
  788. X            (this_path = nextfile(1, (char *) NULL, 0)) != NULL) {
  789. X         char *this_name = nameptr (this_path);
  790. X            modpath (this_path);                    /* do any needed changes to path */
  791. X
  792. X#ifdef IGNORECASE
  793. X#define    COMPARE    strcmpi
  794. X#else
  795. X#define    COMPARE    strcmp
  796. X#endif
  797. X            if (ignore1 != NULL) {
  798. X                if (samefile (this_name,ignore1)  ||    /* exclude ignored files */
  799. X                     samefile (this_name,ignore2)  ||
  800. X                     samefile (this_name,ignore3))
  801. X                    continue;
  802. X
  803. X#ifdef CHEKUDIR
  804. X                if (isuadir(this_path))
  805. X                    continue;
  806. X#else /* CHEKUDIR */
  807. X# ifdef CHEKDIR
  808. X                if (isfdir(this_path))
  809. X                    continue;
  810. X# endif /* CHEKDIR */
  811. X#endif /* CHEKUDIR */
  812. X            } /* end if ignore1 ! = NULL */
  813. X
  814. X/* 
  815. XIf WILDCARD is defined (e.g. AmigaDOS, MS-DOS, VAX/VMS), then nextfile()
  816. Xreturns all filenames and we must now select the ones we need by pattern
  817. Xmatching.  If WILDCARD is not defined (e.g. **IX), filenames have already been
  818. Xselected by the shell and need not be tested again. 
  819. X*/
  820. X#ifdef WILDCARD
  821. X            if (match_half (this_name,pat_name) ||
  822. X                match_half (pat_name, "?-?") &&     /* character range */
  823. X                    *this_name >= *pat_name && *this_name <= pat_name[2])
  824. X#endif
  825. X            {
  826. X#ifdef WILDCARD
  827. X                argok = 1;                                    /* remember arg matched */
  828. X#endif
  829. X                flist[fptr++] = strdup (this_path);
  830. X                if (*longest < strlen(this_path))
  831. X                    *longest = strlen(this_path);
  832. X            }
  833. X
  834. X        } /* end while */
  835. X#ifdef WILDCARD
  836. X        if (argok == 0) {                                    /* no match for argument */
  837. X            prterror ('e', "Could not open %s\n", *argv);
  838. X        }
  839. X#endif
  840. X      argc--;
  841. X      argv++;
  842. X   }
  843. X   /* fptr is now 1 + index of last item in array */
  844. X
  845. X   if (this_path != NULL && fptr >= flistsize)
  846. X      prterror ('w', too_many_files, flistsize);
  847. X#ifndef  DONT_SORT
  848. X   /* Shell sort -- K&R p. 58 */
  849. X   for (gap = fptr/2; gap > 0; gap /= 2)
  850. X      for (i = gap; i < fptr; i++)
  851. X         for (j = i - gap; j >= 0 && 
  852. X            strcmp(flist[j],flist[j+gap]) > 0; j -= gap) {
  853. X            char *t = flist[j]; flist[j] = flist[j+gap]; flist[j+gap] = t;
  854. X         }
  855. X#endif /* DONT_SORT */
  856. X
  857. X   fptr--;     /* fptr is now index of last item in array */
  858. X
  859. X   /* Remove duplicates */
  860. X   for (i = 0; i < fptr; i++) {
  861. X      while (i<fptr && COMPARE(flist[i],flist[i+1]) == 0) {
  862. X         for (j = i; j < fptr; j++)
  863. X            flist[j] = flist[j+1];
  864. X         fptr--;
  865. X      }
  866. X   }
  867. X
  868. X   flist[++fptr] = NULL;      /* NULL entry terminates list */
  869. X}
  870. X
  871. X/*******
  872. Xmodpath() makes any changes needed before pathname is stored;
  873. Xcurrently these could involve folding it to lower case and
  874. Xconverting backslashes to forward slashes
  875. X*/
  876. X
  877. X/*ARGUSED*/
  878. Xvoid modpath (path)
  879. Xchar *path;
  880. X{
  881. X#ifdef FOLD
  882. X    strlwr (path);
  883. X#endif
  884. X
  885. X#ifdef FORCESLASH
  886. X    fixslash (path);                /* convert backslashes to slashes */
  887. X#endif
  888. X}
  889. X
  890. X#ifdef CHEKDIR
  891. X/* Function isfdir returns 1 if pathname is a directory else 0 */
  892. Xint isfdir (this_path)
  893. Xchar *this_path;
  894. X{
  895. X    int dir;
  896. X    ZOOFILE f;  
  897. X    f = zooopen (this_path, Z_READ);
  898. X    if (f == NOFILE)
  899. X        return 0;
  900. X    else {
  901. X        dir = isadir(f);  zooclose(f);
  902. X    }
  903. X    return (dir);
  904. X}
  905. X#endif
  906. END_OF_FILE
  907. if test 6233 -ne `wc -c <'makelist.c'`; then
  908.     echo shar: \"'makelist.c'\" unpacked with wrong size!
  909. fi
  910. # end of 'makelist.c'
  911. fi
  912. if test -f 'misc2.c' -a "${1}" != "-c" ; then 
  913.   echo shar: Will not clobber existing file \"'misc2.c'\"
  914. else
  915. echo shar: Extracting \"'misc2.c'\" \(7457 characters\)
  916. sed "s/^X//" >'misc2.c' <<'END_OF_FILE'
  917. X#ifndef LINT
  918. X/* @(#) misc2.c 2.7 88/01/24 12:47:36 */
  919. Xstatic char sccsid[]="@(#) misc2.c 2.7 88/01/24 12:47:36";
  920. X#endif /* LINT */
  921. X
  922. X/*
  923. XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
  924. X(C) Copyright 1988 Rahul Dhesi -- All rights reserved
  925. X*/
  926. X#include "options.h"
  927. X/* Miscellaneous routines */
  928. X#include "portable.h"
  929. X#include "zooio.h"
  930. X#include "various.h"
  931. X#include "zoofns.h"     /* only for malloc */
  932. X#include "errors.i"
  933. X#include "zoomem.h"
  934. X#include "zoo.h"
  935. X
  936. X#ifdef LINT_ARGS
  937. Xint makepath (char *);
  938. X#else
  939. Xint makepath ();
  940. X#endif
  941. X
  942. X
  943. X/**********************/
  944. X/* memerr() */
  945. X/* Give error message on memory error and abort */
  946. Xvoid memerr()
  947. X{
  948. X#ifdef OOZ
  949. X   prterror ('f', no_memory, "", "");
  950. X#else
  951. X   prterror ('f', no_memory);
  952. X#endif
  953. X}
  954. X
  955. X/**********************/
  956. X/*
  957. Xemalloc() allocates memory like malloc() does, except that it automatically
  958. Xcalls the error function memerr() if memory couldn't be allocated.  It also
  959. Xassumes (unless small memory allocation is being done) that memory will
  960. Xnever be freed and conserves it by allocating memory in large chunks
  961. Xand then partitioning it out with no administrative overhead.
  962. X*/
  963. X
  964. Xchar *emalloc (size)
  965. Xunsigned int size;
  966. X{
  967. X#define  BLOCK_SIZE  512      /* memory allocation granularity */
  968. X
  969. X#ifdef USE_MALLOC
  970. X/* Pass on memory requests to malloc() */
  971. X   char *ptr;
  972. X   if ((ptr = malloc (size)) == NULL)
  973. X      memerr();
  974. X   return (ptr);
  975. X#else
  976. X   static char *memptr;
  977. X   static unsigned avail = 0;
  978. X   unsigned malloc_incr;
  979. X   char *retval;
  980. X
  981. X   if (size == 0)
  982. X      return (NULL);
  983. X
  984. X   /* if not enough space avail get some more */
  985. X   if (avail < size) {
  986. X      malloc_incr = BLOCK_SIZE;
  987. X      if (malloc_incr < size)
  988. X         malloc_incr = size;
  989. X      while (malloc_incr >= size && (memptr = malloc (malloc_incr)) == NULL)
  990. X         malloc_incr = (malloc_incr / 6) * 5;
  991. X      avail = malloc_incr;
  992. X   }
  993. X
  994. X   if (avail < size)
  995. X      memerr();                              /* no return from this */
  996. X   retval = memptr;
  997. X   memptr += size;
  998. X   avail -= size;
  999. X   return (retval);
  1000. X#endif  /* end of not USE_MALLOC */
  1001. X}
  1002. X
  1003. X/**********************/
  1004. X/* putstr()
  1005. XThis function prints a string to standard output.  If the received
  1006. Xstring pointer is NULL, it is handled safely.  This function is here
  1007. Xfor historical reasons:  Ooz was once coded to not use printf under
  1008. XMSDOS to save space, and at that time putstr() printed a string
  1009. Xwithout using printf.  It should eventually be eliminated and all
  1010. Xcalls to it replaced with calls to printf directly.
  1011. X*/
  1012. Xputstr (str)
  1013. Xregister char *str;
  1014. X{
  1015. X   if (str == NULL)
  1016. X      return;
  1017. X    printf ("%s", str);
  1018. X}
  1019. X
  1020. X/**********************/
  1021. X/* exists()
  1022. XThis function checks the existence of a file.  
  1023. X
  1024. XIf the symbol EXISTS is defined, that is called as a macro and
  1025. Xsupplied the filename.  It must return 1 if the file exists and
  1026. X0 if it does not.
  1027. X
  1028. XIf EXISTS is not defined, exists() tests to see if the file can be 
  1029. Xopened for reading or writing;  if so, it returns 1 else it returns 0. 
  1030. X
  1031. XBecause of the delay between the time existence is checked and the time Zoo
  1032. Xcreates a files, a race condition exists.  It would be better to
  1033. Xuse open() with the O_EXCL flag but that will not work for many
  1034. Xsystems.
  1035. X*/
  1036. X
  1037. Xint exists (fname)
  1038. Xchar *fname;
  1039. X{
  1040. X#ifdef EXISTS
  1041. X    return EXISTS(fname);
  1042. X#else
  1043. X   ZOOFILE f;
  1044. X
  1045. X   if ( (f = zooopen (fname, Z_READ )) != NOFILE ||
  1046. X          (f = zooopen (fname, Z_WRITE)) != NOFILE ) {
  1047. X      zooclose (f);
  1048. X      return (1);
  1049. X   } else
  1050. X      return (0);
  1051. X#endif /* ifdef EXISTS */
  1052. X}
  1053. X
  1054. X/****************
  1055. Xnewcat() allocates enough space to concatenate two strings then returns
  1056. Xa pointer to the concatenated result */
  1057. X
  1058. Xchar *newcat (r, s)
  1059. Xchar *r, *s;
  1060. X{
  1061. X   char *temp = emalloc (strlen (r) + strlen (s) + 2); /* 1 spare */
  1062. X   strcpy (temp, r);
  1063. X   strcat (temp, s);
  1064. X   return (temp);
  1065. X}
  1066. X
  1067. X
  1068. X/* Creates a path */
  1069. Xint makepath(path)
  1070. Xchar *path;
  1071. X{
  1072. X   char tmppath[PATHSIZE];
  1073. X   char *slashpos;
  1074. X   if (path == NULL)
  1075. X      return;
  1076. X   while (*lastptr(path) == *PATH_CH)     /* remove trailing slashes */
  1077. X      *lastptr(path) = '\0';
  1078. X   if (*path == '\0')
  1079. X      return;
  1080. X
  1081. X   slashpos = findlast(path, PATH_CH);    /* find last slash */
  1082. X   if (slashpos == NULL) {                /* if not, just create dir. */
  1083. X      MKDIR(path);
  1084. X      return;
  1085. X   } else {                               /* otherwise...         */
  1086. X      if (slashpos == path) {             /* if leading slash */
  1087. X         MKDIR(slashpos);                 /* make that directory */
  1088. X         return;                          /* and done */
  1089. X      } else {
  1090. X         strcpy(tmppath,path);            /* save path */
  1091. X         *slashpos = '\0';                /* split into prefix & suffix */
  1092. X#ifdef DEBUG
  1093. X         printf("making path from [%s]\n", path);
  1094. X#endif
  1095. X         makepath(path);                     /* make path from prefix */
  1096. X#ifdef DEBUG
  1097. X         printf("making dir from [%s]\n", tmppath);
  1098. X#endif
  1099. X         MKDIR(tmppath);                  /* make dir from suffix */
  1100. X      }
  1101. X   }
  1102. X} /* makepath() */
  1103. X
  1104. X/*
  1105. XIf no extension in filename add supplied extension
  1106. X*/
  1107. Xchar *addext (fname, ext)
  1108. Xchar *fname;
  1109. Xchar *ext;
  1110. X{
  1111. X   if (strchr (nameptr (fname), EXT_CH) == NULL)
  1112. X      return (newcat (fname, ext));
  1113. X   else
  1114. X      return (fname);
  1115. X}
  1116. X
  1117. X#ifdef VER_CH       /* remove any trailing extension field */
  1118. Xchar *strip_ver (fname)
  1119. Xchar *fname;
  1120. X{
  1121. X   char *p = strchr (fname, VER_CH);
  1122. X   if (p != NULL)
  1123. X      *p = '\0';
  1124. X}
  1125. X#endif
  1126. X
  1127. X/*
  1128. XFunction samefile() compares two filenames to see if they are the
  1129. Xsame file.  Just strcmp() or strcmpi() could have been used, except
  1130. Xthat if the filenames have trailing version fields, we want to
  1131. Xcompare those always equal.  samefile() is called by routines
  1132. Xthat want to avoid adding an archive to itself.
  1133. X*/
  1134. Xint samefile (f1, f2)
  1135. Xchar *f1;
  1136. Xchar *f2;
  1137. X{
  1138. X#ifdef IGNORECASE
  1139. X#define COMPARE strcmpi
  1140. X#else
  1141. X#define COMPARE strcmp
  1142. X#endif
  1143. X
  1144. X#ifdef VER_CH
  1145. X   char tf1[LFNAMESIZE];
  1146. X   char tf2[LFNAMESIZE];
  1147. X   strcpy (tf1, f1);
  1148. X   strcpy (tf2, f2);
  1149. X   strip_ver (tf1);   /* strip version fields */
  1150. X   strip_ver (tf2);
  1151. X   return (COMPARE (tf1, tf2) == 0);
  1152. X#else
  1153. X/* if no version fields, just use strcmp(i) */
  1154. X   return (COMPARE (f1, f2) == 0);
  1155. X#endif
  1156. X}
  1157. X
  1158. X#ifdef USE_ASCII
  1159. Xint isdigit (c)
  1160. Xchar c;
  1161. X{
  1162. X    return (c >= '0' && c <= '9');
  1163. X}
  1164. Xint isupper (c)
  1165. Xchar c;
  1166. X{
  1167. X    return (c >= 'A' && c <= 'Z');
  1168. X}
  1169. X
  1170. Xint toascii (c)
  1171. Xchar c;
  1172. X{
  1173. X    return (c & 0x7f);
  1174. X}
  1175. X
  1176. Xint tolower (c)
  1177. Xchar c;
  1178. X{
  1179. X    return (isupper(c) ? (c | 0x20) : c);
  1180. X}
  1181. X#endif
  1182. X
  1183. X#ifdef GETTZ
  1184. X/****************
  1185. XFunction tzadj() accepts a directory entry and adjusts its timestamp
  1186. Xto reflect its timezone.  Uses function mstime() from mstime.i
  1187. Xand mstonix() from nixtime.i.
  1188. X*/
  1189. X
  1190. Xlong mstonix();
  1191. Xlong gettz();
  1192. X#include "mstime.i"    /* get mstime() */
  1193. X
  1194. Xvoid tzadj (direntry)
  1195. Xstruct direntry *direntry;
  1196. X{
  1197. X    long diff_tz;
  1198. X    long longtime;
  1199. X    if (direntry->tz == NO_TZ)        /* none stored */
  1200. X        return;
  1201. X    diff_tz = (long) direntry->tz * (3600/4) - gettz(); /* diff. in seconds */
  1202. X    longtime = mstonix (direntry->date, direntry->time) + diff_tz; /* adj tz */
  1203. X    mstime (longtime, &direntry->date, &direntry->time);
  1204. X}
  1205. X#endif /* GETTZ */
  1206. X
  1207. X/* how long an int can be in text form -- allow 64-bit ints */
  1208. X#define INT_TEXT 21
  1209. X
  1210. X/* Function add_version adds a version suffix to a filename, given
  1211. Xthe directory entry corresponding to the file */
  1212. Xvoid add_version (fname, direntry)
  1213. Xchar *fname;
  1214. Xstruct direntry *direntry;
  1215. X{
  1216. X    char verstr[INT_TEXT];    /* string buffer for conversion to text */
  1217. X    if (direntry->vflag & VFL_ON) {
  1218. X        sprintf (verstr, "%u", direntry->version_no);
  1219. X        strcat (fname, VER_DISPLAY);
  1220. X        strcat (fname, verstr);
  1221. X    }
  1222. X}
  1223. END_OF_FILE
  1224. if test 7457 -ne `wc -c <'misc2.c'`; then
  1225.     echo shar: \"'misc2.c'\" unpacked with wrong size!
  1226. fi
  1227. # end of 'misc2.c'
  1228. fi
  1229. if test -f 'parse.c' -a "${1}" != "-c" ; then 
  1230.   echo shar: Will not clobber existing file \"'parse.c'\"
  1231. else
  1232. echo shar: Extracting \"'parse.c'\" \(5640 characters\)
  1233. sed "s/^X//" >'parse.c' <<'END_OF_FILE'
  1234. X#ifndef LINT
  1235. Xstatic char sccsid[]="@(#) parse.c 2.1 87/12/25 12:24:10";
  1236. X#endif /* LINT */
  1237. X
  1238. X/*
  1239. XThe contents of this file are hereby released to the public domain.
  1240. X
  1241. X                                 -- Rahul Dhesi 1986/11/14
  1242. X
  1243. X*/
  1244. X
  1245. X#include "options.h"
  1246. X#include "zoo.h"
  1247. X#include "zooio.h"
  1248. X#include "various.h"
  1249. X#include "zoofns.h"
  1250. X
  1251. X#include "parse.h"
  1252. X#include "assert.h"
  1253. X
  1254. X/*
  1255. Xparse() accepts a filename and return its component parts in a structure.
  1256. XThe component parts are:  disk drive, path prefix, root name of filename, 
  1257. Xand extension.  
  1258. X
  1259. XIf DISK_CH is not defined, it is assumed that filenames may be
  1260. Xpreceded with a disk prefix terminated by the character DISK_CH.
  1261. XThe first character of the disk prefix, followed by DISK_CH,
  1262. Xis returned in the drive field.
  1263. X
  1264. XIf the symbol DISK_CH is defined, a null string is returned in the
  1265. Xdisk field.
  1266. X*/
  1267. Xvoid parse (path_st, fname)
  1268. Xregister struct path_st *path_st;
  1269. Xchar *fname;
  1270. X{
  1271. X   char tempname[LFNAMESIZE];       /* working copy of supplied fname */
  1272. X   char *namep;                   /* points to relevant part of tempname */
  1273. X
  1274. X   char *p;
  1275. X   strcpy (tempname, fname);
  1276. X
  1277. X#ifdef DEBUG
  1278. Xprintf ("parse:  supplied name is [%s].\n", tempname);
  1279. X#endif
  1280. X
  1281. X#ifndef DISK_CH
  1282. X   path_st->drive[0] = '\0';
  1283. X   namep = tempname;           /* points to pathname+filename */
  1284. X#else
  1285. X   path_st->drive[0] = '\0';
  1286. X   p = strchr (tempname, DISK_CH);      /* point to first ':' */
  1287. X
  1288. X   if (p != NULL) {
  1289. X      path_st->drive[0] = *tempname;/* use only first char of drive name */
  1290. X      path_st->drive[1] = DISK_CH;
  1291. X      path_st->drive[2] = '\0';
  1292. X      namep = ++p;                /* point to pathname+filename */
  1293. X   } else {
  1294. X      path_st->drive[0] = '\0';
  1295. X      namep = tempname;           /* points to pathname+filename */
  1296. X   }
  1297. X#endif /* end of not DISK_CH */
  1298. X   
  1299. X   /* Note:  findlast() finds last occurrence in the subject string of 
  1300. X      any one of a set of chars */
  1301. X
  1302. X   /* save the long filename */
  1303. X   p = findlast (namep, PATH_SEP);
  1304. X
  1305. X   /* if path separator found, copy next char onwards; else entire string */
  1306. X   strncpy (path_st->lfname,
  1307. X               (p != NULL) ? p+1 : namep,
  1308. X               LFNAMESIZE);
  1309. X   path_st->lfname[LFNAMESIZE-1] = '\0';     /* force null termination */
  1310. X
  1311. X#ifdef DEBUG
  1312. Xprintf ("parse:  path = [%s] long filename = [%s]\n", 
  1313. X         namep, path_st->lfname);
  1314. X#endif
  1315. X
  1316. X/* Separate out the extension */
  1317. Xp = findlast (namep, EXT_SEP);                        /* look for . or /        */
  1318. Xif (p != NULL && *p != EXT_CH)                        /* found .?                    */
  1319. X    p = NULL;                                                /* ... if not, ignore / */
  1320. X
  1321. X#ifdef DEBUG
  1322. Xif (p == NULL)
  1323. X   printf ("parse:  no extension found for [%s]\n", namep);
  1324. Xelse
  1325. X   printf ("parse:  extension for [%s] is [%s]\n", namep, p);
  1326. X#endif
  1327. X   
  1328. X   path_st->ext[0] = '\0';                      /* assume no extension  */
  1329. X   if (p != NULL) {                             /* found extension      */
  1330. X      strncpy (path_st->ext, (p+1), EXTLEN);    /* save extension       */
  1331. X      path_st->ext[EXTLEN] = '\0';              /* force termination    */
  1332. X      *p = '\0';                                /* null out extension   */
  1333. X   }
  1334. X
  1335. X   /* separate out root of filename if any */
  1336. X   p = findlast (namep, PATH_SEP);
  1337. X
  1338. X   if (p != NULL) {
  1339. X      ++p;
  1340. X      strncpy (path_st->fname, p, ROOTSIZE);  /* save filename        */
  1341. X      *p = '\0';               /* null out filename */
  1342. X   } else {
  1343. X      strncpy (path_st->fname, namep, ROOTSIZE);
  1344. X      *namep = '\0';                   /* null out filename    */
  1345. X   }
  1346. X   path_st->fname[ROOTSIZE] = '\0';           /* force termination    */
  1347. X
  1348. X   /* what remains, whether null or not, is the path prefix */
  1349. X   path_st->dir[0] = '\0';             /* in case *namep is '\0' */
  1350. X
  1351. X   strncpy (path_st->dir, namep, PATHSIZE);
  1352. X
  1353. X   /* remove trailing path-separater from directory name, but don't
  1354. X      remove it if it is also the leading separater */
  1355. X   { 
  1356. X      int n;
  1357. X      n = strlen(path_st->dir);
  1358. X      if (n != 1)
  1359. X         path_st->dir[n-1] = '\0';
  1360. X   }
  1361. X
  1362. X#ifdef DEBUG
  1363. Xprintf ("parse:  path prefix = [%s].\n", namep);
  1364. X#endif
  1365. X   /* if extension is null, and if long filename contains more than
  1366. X      ROOTSIZE  characters, transfer some of them to extension */
  1367. X   if (path_st->ext[0] == '\0' && strlen(path_st->lfname) > ROOTSIZE) {
  1368. X      strncpy(path_st->ext, &path_st->lfname[ROOTSIZE], EXTLEN);
  1369. X      path_st->ext[3] = '\0';
  1370. X   }
  1371. X}
  1372. X
  1373. X/*******************/
  1374. X/* 
  1375. Xfindlast() finds last occurrence in provided string of any of the characters
  1376. Xexcept the null character in the provided set.
  1377. X
  1378. XIf found, return value is pointer to character found, else it is NULL.
  1379. X*/
  1380. X
  1381. Xchar *findlast (str, set)
  1382. Xregister char *str;        /* subject string     */
  1383. Xchar *set;                 /* set of characters to look for */
  1384. X
  1385. X{
  1386. X   register char *p;
  1387. X
  1388. X   if (str == NULL || set == NULL || *str == '\0' || *set == '\0')
  1389. X      return (NULL);
  1390. X
  1391. X   p = lastptr (str);   /* pointer to last char of string */
  1392. X   assert(p != NULL);
  1393. X
  1394. X   while (p != str && strchr (set, *p) == NULL) {
  1395. X      --p;
  1396. X   }                 
  1397. X
  1398. X   /* either p == str or we found a character or both */
  1399. X   if (strchr (set, *p) == NULL)
  1400. X      return (NULL);
  1401. X   else
  1402. X      return (p);
  1403. X}
  1404. X
  1405. X/*******************/
  1406. X/*
  1407. Xlastptr() returns a pointer to the last non-null character in the string, if
  1408. Xany.  If the string is null it returns NULL
  1409. X*/
  1410. X
  1411. Xchar *lastptr (str)
  1412. Xregister char *str;                 /* string in which to find last char */
  1413. X{
  1414. X   register char *p;
  1415. X   if (str == NULL)
  1416. X      prterror ('f', "lastptr:  received null pointer\n");
  1417. X   if (*str == '\0')
  1418. X      return (NULL);
  1419. X   p = str;
  1420. X   while (*p != '\0')            /* find trailing null char */
  1421. X      ++p;
  1422. X   --p;                          /* point to just before it */
  1423. X   return (p);
  1424. X}
  1425. END_OF_FILE
  1426. if test 5640 -ne `wc -c <'parse.c'`; then
  1427.     echo shar: \"'parse.c'\" unpacked with wrong size!
  1428. fi
  1429. # end of 'parse.c'
  1430. fi
  1431. if test -f 'prterror.c' -a "${1}" != "-c" ; then 
  1432.   echo shar: Will not clobber existing file \"'prterror.c'\"
  1433. else
  1434. echo shar: Extracting \"'prterror.c'\" \(5399 characters\)
  1435. sed "s/^X//" >'prterror.c' <<'END_OF_FILE'
  1436. X#ifndef LINT
  1437. X/* @(#) prterror.c 2.8 88/01/31 18:48:17 */
  1438. Xstatic char sccsid[]="@(#) prterror.c 2.8 88/01/31 18:48:17";
  1439. X#endif /* LINT */
  1440. X
  1441. X/*
  1442. XThe contents of this file are hereby released to the public domain.
  1443. X
  1444. X                                 -- Rahul Dhesi 1986/11/14
  1445. X
  1446. X*/
  1447. X#include "options.h"
  1448. X#ifndef    OK_STDIO
  1449. X#include <stdio.h>
  1450. X#define    OK_STDIO
  1451. X#endif
  1452. X#include "various.h"
  1453. X/* General error handler.  Input format:
  1454. X
  1455. X   parameter 1:  'w', 'e', or 'f'.
  1456. X
  1457. X      'm':  message
  1458. X      'M':  message without preceding identification
  1459. X      'w':  WARNING
  1460. X      'e':  ERROR
  1461. X      'f':  FATAL
  1462. X      'F':  FATAL but program doesn't exist immediately
  1463. X
  1464. X   All text printed is preceded by "Zoo:  " or "Ooz:  "  depending
  1465. X   upon conditional compilation, except in the case of 'M' messages
  1466. X   which are printed without any text being added.
  1467. X
  1468. X   For messages, the text supplied is printed if and only if the global
  1469. X   variable "quiet" is zero.  Control then returns to the caller.
  1470. X
  1471. X   For warnings, errors, and fatal errors, the variable "quiet" is used
  1472. X    as follows.  Warning messages are suppressed if quiet > 1;  error
  1473. X    messages are suppressed if quiet > 2.  Fatal error messages are 
  1474. X    never suppressed--doing so would be a bit risky.
  1475. X
  1476. X   For warnings and errors, the error message is preceded by the "WARNING:"
  1477. X   or "ERROR".  The error message is printed and control returns to the
  1478. X   caller.
  1479. X
  1480. X   For fatal errors, the error message is preceded by "FATAL:" and an
  1481. X   error message is printed.  If the option was 'f', the program exits with 
  1482. X   a status of 1.  If the option was 'F', control returns to the caller and 
  1483. X   it is assumed that the caller will do any cleaning up necessary and then 
  1484. X   exit with an error status.
  1485. X
  1486. X   parameter 2:  The format control string for printf.   
  1487. X   parameters 3 and 4 are passed along to printf.
  1488. X
  1489. X    NOTE
  1490. X   (a) printf() is always supplied parameters 3 through 6, even if they 
  1491. X    were not on the parameter list passed to prterror().  It is assumed 
  1492. X    that printf() will only use as many as are specified by the format 
  1493. X    string.  There is a small chance that on some machines, this will cause 
  1494. X    some kind of stack exception (e.g. if the hardware maintains tag 
  1495. X    bits in each word on the stack and doesn't allow certain types of 
  1496. X    data to be arbitrarily accessed).  This is just a theory so far.
  1497. X
  1498. X    (b) Parameter passing relies on consecutive small parameters being
  1499. X    properly interpreted as a single larger parameter when needed.
  1500. X    Eventually var_args should be used, but not all systems probably
  1501. X    have it at the moment.
  1502. X
  1503. X    (c) All messages, whether informative or error, are sent to standard
  1504. X    output via printf.  It might be a good idea to eventually send 'e' and
  1505. X    'f' class messages to the standard error stream.  Best would be
  1506. X    some way of telling if standard output and standard error are not
  1507. X    the same device, so that we could always send error messages to
  1508. X    standard error, and also duplicate them to standard output if 
  1509. X    different from standard error.  There seems to be no way
  1510. X    of doing this in the general case.
  1511. X*/
  1512. X
  1513. Xextern int quiet;
  1514. X
  1515. X/* These declarations must be equivalent to those in errors.i */
  1516. Xchar no_match[] = "No files matched.\n";
  1517. Xchar failed_consistency[] = "Archive header failed consistency check.\n";
  1518. Xchar invalid_header[] = "Invalid or corrupted archive.\n";
  1519. Xchar internal_error[]="Internal error.\n";
  1520. Xchar disk_full[]      = "I/O error or disk full.\n";
  1521. Xchar bad_directory[]  = "Directory entry in archive is invalid.\n";
  1522. Xchar no_memory[] = "Ran out of memory.\n";
  1523. Xchar too_many_files[] = "Some filenames ignored -- can only handle %d.\n";
  1524. Xchar packfirst[] = "Old format archive -- please pack first with P command.\n";
  1525. Xchar garbled[] = "Command is garbled.\n";
  1526. Xchar start_ofs[] = "Starting at %ld (offset %ld)\n";
  1527. X
  1528. X#ifndef OOZ
  1529. Xchar wrong_version[]=
  1530. X   "Zoo %d.%d or later is needed to fully manipulate this archive.\n";
  1531. Xchar cant_process[] =
  1532. X   "The rest of the archive (%lu bytes) cannot be processed.\n";
  1533. Xchar option_ignored[] = "Ignoring option %c.\n";
  1534. Xchar inv_option[] = "Option %c is invalid.\n";
  1535. Xchar bad_crc[] = "\007Bad CRC, %s probably corrupted\n";
  1536. X#endif
  1537. X
  1538. X#ifdef OOZ
  1539. Xchar could_not_open[] = "Could not open ";
  1540. X#else
  1541. Xchar could_not_open[] = "Could not open %s.\n";
  1542. X#endif
  1543. X
  1544. X#ifdef LINT_ARGS
  1545. X/* defined in zoofns.h but we don't want to include that and waste time */
  1546. Xvoid prterror (int, char *, MORE);
  1547. Xvoid zooexit (int);
  1548. X#endif
  1549. X
  1550. X
  1551. X/*VARARGS2*/
  1552. Xvoid prterror(level, format, a, b, c, d)
  1553. Xregister int level;
  1554. Xchar *format, *a, *b, *c, *d;
  1555. X
  1556. X{
  1557. X   char string[120];       /* local format string */
  1558. X   *string = '\0';         /* get a null string to begin with */
  1559. X
  1560. X#ifdef OOZ
  1561. X   strcpy (string, "Ooz:  ");
  1562. X#else
  1563. X   strcpy (string, "Zoo:  ");
  1564. X#endif
  1565. X
  1566. X   switch (level) {
  1567. X      case 'M': *string = '\0';                    /* fall through to 'm' */
  1568. X      case 'm': if (quiet) return; break;
  1569. X      case 'w': 
  1570. X            if (quiet > 1) return;
  1571. X            strcat (string, "WARNING:  "); break;
  1572. X      case 'e': 
  1573. X            if (quiet > 2) return;
  1574. X            strcat (string, "ERROR:  ");   break;
  1575. X      case 'F':
  1576. X      case 'f': strcat (string, "FATAL:  ");   break;
  1577. X      default: prterror ('f', internal_error);  /* slick recursive call */
  1578. X   }
  1579. X
  1580. X   strcat (string, format);      /* just append supplied message */
  1581. X
  1582. X   printf (string, a, b, c, d);   /* and print the whole thing */
  1583. X    fflush (stdout);
  1584. X
  1585. X   if (level == 'f')       /* and abort on fatal error 'f' but not 'F' */
  1586. X      zooexit (1);
  1587. X}
  1588. END_OF_FILE
  1589. if test 5399 -ne `wc -c <'prterror.c'`; then
  1590.     echo shar: \"'prterror.c'\" unpacked with wrong size!
  1591. fi
  1592. # end of 'prterror.c'
  1593. fi
  1594. echo shar: End of archive 3 \(of 10\).
  1595. cp /dev/null ark3isdone
  1596. MISSING=""
  1597. for I in 1 2 3 4 5 6 7 8 9 10 ; do
  1598.     if test ! -f ark${I}isdone ; then
  1599.     MISSING="${MISSING} ${I}"
  1600.     fi
  1601. done
  1602. if test "${MISSING}" = "" ; then
  1603.     echo You have unpacked all 10 archives.
  1604.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1605. else
  1606.     echo You still need to unpack the following archives:
  1607.     echo "        " ${MISSING}
  1608. fi
  1609. ##  End of shell archive.
  1610. exit 0
  1611.